<template>
  <div>
    <h1>三级分类页面</h1>
    <!-- <p>电商分类最多为三级,拖拽之后总的层数不能超过3</p>
    <p>拖拽分为两种类型：前后，内部</p>
    <p>
      思路：1、拖拽肯定为两个节点(被拖拽的节点，目标对象)之间的交互<br>
      1.需要判断被拖拽的节点的层数(计算拖拽的层数)<br>
      2.需要根据拖拽类型和目标对象的层数判断(判断是否能被拖拽)<br>
      3.把拖拽之后的的结果同步数据库<br>
    </p> -->
    <el-switch v-model="draggable" active-color="#13ce66" inactive-color="#ff4949"></el-switch>开启拖拽
    <el-tree 
      :default-expanded-keys="defaultExpandedKeys"
      node-key="catId" 
      @node-drop="nodeDrop" 
      :allow-drop="allowDrop" 
      :draggable="draggable" 
      :data="data" 
      :props="defaultProps" 
      :expand-on-click-node="false">
      <span class="custom-tree-node" slot-scope="{ node, data }">
        <span>{{ node.label }}</span>
        <span>
          <el-button v-if="data.children.length>0" type="text" size="mini" @click="() => append(data)">
            Append
          </el-button>
          <el-button type="text" size="mini" @click="() => update(data)">
            Update
          </el-button>
          <el-button v-if="node.childNodes.length == 0" type="text" size="mini" @click="() => remove(node, data)">
            Delete
          </el-button>
        </span>
      </span>
    </el-tree>

    <el-dialog title="三级分类保存页面" :visible.sync="dialogFormVisible">
      <el-form :model="category">
        <el-form-item label="分类名称" :label-width="formLabelWidth">
          <el-input v-model="category.name" autocomplete="off"></el-input>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogFormVisible = false">取 消</el-button>
        <el-button type="primary" @click="dialogFormVisible = false;save()">确 定</el-button>
      </div>
    </el-dialog>
  </div>
</template>
<script>
export default {
  data() {
    return {
      defaultExpandedKeys:[],
      draggable:false,
      updateNodes:[],
      pid:0,
      level:1,
      catLevel:1,
      category: {},
      data: [],
      dialogFormVisible: false,
      formLabelWidth: "120px",
      defaultProps: {
        children: "children",
        label: "name",
      },
    };
  },
  created() {
    
    this.getDateList();
  },
  methods: {
    //和数据库交互 同步数据
    /**
     * draggingNode 被拖拽的对象
     * dropNode 目标对象
     * type 拖拽的类型 before after inner
     * 因为拖拽的类型不同，有可能会改变pid的值
     * 如果拖拽的类型为before 或者 after 那么pid值就是目标对象的pid
     * 如果拖拽的类型为inner 那么pid就是目标对象的catid
     * 数据库需要改变的字段 ： parentCid,catId,catLevel,sort
     * 前台需要给后台传递的参数？
     * 已知的条件：
     * 如果拖拽成功 dropNode 中已经有的最新数据
     * 需要给后台提交的参数中又要根据拖拽类型判断
     * 如果拖拽类型为前后，需要获取的对象就是目标对象的父元素的子元素
     * 如果拖拽类型为内部，需要获取目标对象的子元素
     * 我们获取到的数据都是数组 前台传递到后台的数据是一个数组，后台实现批量修改
     * 
     * 1、第一个未知条件
     * parentCid
     * 2、第二个未知条件
     * cat_level 每次改变都需要传递到后台吗？
     * 如果拖拽类型为 前后 新的层级就是目标对象的层级
     * 如果拖拽类型为 内部 新的层级就是目标对象层级+1
     * 3、第三个未知条件
     * sort
     * 拖拽类型为前后 排序就是目标对象的父元素的子元素集合的小标
     * 拖拽类型为内部 排序就是目标对象的子元素的下标
     */
    nodeDrop(draggingNode, dropNode, type) {
      //console.log("拖拽成功",draggingNode, dropNode, type)
        if(type == "before" || type == "after") {
          this.pid = dropNode.data.parentCid;
          //计算层级
          let flag = false;
          let updateChildrenNode = null;
          if(draggingNode.data.catLevel != dropNode.data.catLevel) {
            this.level = dropNode.data.catLevel;
            flag = true;
            updateChildrenNode = draggingNode;
          }
          if(this.pid == 0) {
            this.getUpdateNodes(dropNode.parent.data,flag,updateChildrenNode);
          }else {
            this.getUpdateNodes(dropNode.parent.data.children,flag,updateChildrenNode);
          }
        }else if(type == "inner") {
          this.pid = dropNode.data.catId;
          //计算层级
          this.level = dropNode.data.catLevel + 1;
          //收集数据
          this.getUpdateNodes(dropNode.data.children,false,null);
        }
        //查看收集之后的结果
        // console.log("收集的数据为：",this.updateNodes);
        if(this.category.catId) mehtodUrl = "update"
        this.$http({
        url: this.$http.adornUrl(`/product/category/updateNodes`),
        method: "post",
        data: this.$http.adornData(this.updateNodes, false),
      }).then(({data})=>{
        console.log(data);
        if (data.code == 0) {
          this.$message({
          message: '拖拽成功',
          type: 'success'
        });
          this.updateNodes = [];
          this.getDateList();
        }
      })
    },
    //收集后台需要的数据  需要一个表示 来表名我们是否需要收集子元素
    //node是被拖拽的对象
    getUpdateNodes(nodes,flag,node,level = this.level,pid = this.pid) {
      console.log("需要被收集的元素",nodes);
      console.log("被拖拽的对象",node);
      for(var i = 0;i<nodes.length;i++) {
        //var obj = {catId:nodes[i].catId,name:nodes[i].name,parentCid:this.pid,catLevel:this.level,sort:i}
        this.updateNodes.push({catId:nodes[i].catId,name:nodes[i].name,parentCid:pid,catLevel:level,sort:i});
      }
      if(flag) {
          if(node!=null) {
            this.getUpdateNodes(node.data.children,false,null,this.level+1,node.data.catId);
          }
        }
    },
    /**
     * draggingNode 被拖拽的对象
     * dropNode 目标对象
     * type 拖拽的类型
     */
    allowDrop(draggingNode, dropNode, type) {
        // console.log(draggingNode, dropNode, type)
      //1、计算被拖拽对象的层数
      this.getCountLevel(draggingNode);
      // console.log("被拖拽对象的层数:",this.catLevel);
      if(type == "next" || type == "prev") {
        if(this.catLevel == 1) return true;
        if(this.catLevel == 2 && dropNode.data.catLevel!=3) return true;
        if(this.catLevel == 3 && dropNode.data.catLevel==1) return true;
      }else if(type == "inner") {
        if(this.catLevel == 1 && dropNode.data.catLevel!=3) return true;
        if(this.catLevel == 2 && dropNode.data.catLevel==1) return true;
      }
        return false;
    },
    getCountLevel(node) {//node是被拖拽的对象
      this.catLevel =  1;
      if(node.childNodes.length>0) {
        this.catLevel = 2;
        for(var i in node.childNodes) {
          if(node.childNodes[i].childNodes.length>0) {
            this.catLevel = 3;
            return ;
          }
        }
      }
    },
    remove(node,data) {
      console.log(node,data)
      var ids = [];
      ids.push(node.data.catId)
      this.$http({
        url: this.$http.adornUrl(`/product/category/delete/`),
        method: "post",
        data: this.$http.adornData(ids, false),
      }).then(({data})=>{
        console.log(data);
        if(data.code == 0 ) {
          this.$message({
          message: '恭喜你，这是一条成功消息',
          type: 'success'
        });
        this.getDateList();
        }
      })
    },
    update(node) {
      this.dialogFormVisible = true;
        this.$http({
        url: this.$http.adornUrl(`/product/category/info/${node.catId}`),
        method: "get",
        params: this.$http.adornParams(),
        }).then(({ data }) => {
        console.log(data);
          console.log(data);
          this.category = data.category;
        })
    },
    save() {
      let mehtodUrl = "save";
      if(this.category.catId) mehtodUrl = "update"
        this.$http({
        url: this.$http.adornUrl(`/product/category/${mehtodUrl}`),
        method: "post",
        data: this.$http.adornData(this.category, false),
      }).then(({ data }) => {
        console.log(data);
        if (data.code == 0) {
          this.$message({
          message: '保存成功',
          type: 'success'
        });
          this.defaultExpandedKeys = [this.category.parentCid];
          this.category = {};
          this.getDateList();
        }
      });
    },
    append(node) {
      console.log(node);
      this.category.parentCid = node.catId;
      this.category.catLevel = node.catLevel + 1;
      this.category.showStatus = 1;
      this.category.sort = 0;
      this.dialogFormVisible = true;
    },
    getDateList() {
      this.$http({
        url: this.$http.adornUrl("/product/category/tree/list"),
        method: "get",
        params: this.$http.adornParams(),
      }).then(({ data }) => {
        console.log(data);
        this.data = data.page;
      });
    },
  },
};
</script>
